package iosu.java.games.razer.api;

import iosu.java.games.razer.server.ServerCar;

import java.security.InvalidParameterException;
import java.util.Arrays;
import java.util.UUID;

/**
 * Esta clase implementa un mensaje entre cliente y servidor
 * Dependiendo del tipo de mensaje, los posibles contenidos son
 * - fecha en milisegundos
 * - id cliente
 * - 
 * @author iosu
 *
 */
public class RazerProtocolMessage {
	private byte messagetype;
	private byte[] messagecontent;
	
	// para un mensaje de tipo hellorequest, tengo
	private long hora;
	private UUID idcliente;
	// para un mensaje de tipo helloresponse, joingamerequest, tengo
	private int idfromserver;
	// para un mensaje de tipo playeraddedresponse tengo
	private int numCar;
	// para un mensaje de tipo carupdate_request tengo
	private ServerCar defaultcarupdate;
	// para un mensaje de tipo carupdate_response tengo
	private ServerCar car1update;
	private ServerCar car2update;
	private ServerCar car3update;
	private ServerCar car4update;
	
	private int[] results;
	
	public RazerProtocolMessage(byte type){
		switch(type){
			case IRazerProtocol.HELLO_REQUEST:
				this.messagetype = IRazerProtocol.HELLO_REQUEST;
				break;
			case IRazerProtocol.HELLO_RESPONSE:
				this.messagetype = IRazerProtocol.HELLO_RESPONSE;
				break;
			case IRazerProtocol.CREATEGAME_REQUEST:
				this.messagetype = IRazerProtocol.CREATEGAME_REQUEST;
				break;
			case IRazerProtocol.CREATEGAME_RESPONSE:
				this.messagetype = IRazerProtocol.CREATEGAME_RESPONSE;
				break;
			case IRazerProtocol.JOINGAME_REQUEST:
				this.messagetype = IRazerProtocol.JOINGAME_REQUEST;
				break;
			case IRazerProtocol.NOGAMETOJOIN_RESPONSE:
				this.messagetype = IRazerProtocol.NOGAMETOJOIN_RESPONSE;
				break;
			case IRazerProtocol.PLAYERADDED_RESPONSE:
				this.messagetype = IRazerProtocol.PLAYERADDED_RESPONSE;
				break;
			case IRazerProtocol.GAMEREADY_REQUEST:
				this.messagetype = IRazerProtocol.GAMEREADY_REQUEST;
				break;
			case IRazerProtocol.GAMEREADY_RESPONSE:
				this.messagetype = IRazerProtocol.GAMEREADY_RESPONSE;
				break;	
			case IRazerProtocol.NOOP_RESPONSE:
				this.messagetype = IRazerProtocol.NOOP_RESPONSE;
				break;
			case IRazerProtocol.CARUPDATE_REQUEST:
				this.messagetype = IRazerProtocol.CARUPDATE_REQUEST;
				break;
			case IRazerProtocol.CARUPDATE_RESPONSE:
				this.messagetype = IRazerProtocol.CARUPDATE_RESPONSE;
				break;
			case IRazerProtocol.CLOSING_REQUEST:
				this.messagetype = IRazerProtocol.CLOSING_REQUEST;
				break;
			case IRazerProtocol.CARFINISHED_REQUEST:
				this.messagetype = IRazerProtocol.CARFINISHED_REQUEST;
				break;
			case IRazerProtocol.CARFINISHED_RESPONSE:
				this.messagetype = IRazerProtocol.CARFINISHED_RESPONSE;
				break;
			case IRazerProtocol.GAMEFINISHED_REQUEST:
				this.messagetype = IRazerProtocol.GAMEFINISHED_REQUEST;
				break;
			default: throw new UnsupportedOperationException("el codigo "+type+" recibido no se" +
					"corresponde con ningun tipo conocido de mensaje");
		}
	}
	
	public void setMessageContent(byte[] c){
		this.messagecontent = c;
	}
	
	public byte[] getMessageContent(){
		return this.messagecontent;
	}
	
	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder(this.messagecontent.length);
		sb.append("RazerProtocolMessage type: ").append(this.getMesageTypeAsString()).append(", content: ").append(Arrays.toString(this.messagecontent));
		//for (byte b:messagecontent) {
		 //   sb.append(b+'0'); //offset the byte value with the value of char '0'
		//}
		return sb.toString();
	}

	//*************** metodos para HELLO_REQUEST
	public long getHora() {
		return hora;
	}

	public void setHora(long hora) {
		if(this.messagetype!=IRazerProtocol.HELLO_REQUEST) 
			throw new InvalidParameterException("intento de setear hora cuando el mensaje no es de tipo HELLO_REQUEST");
		this.hora = hora;
	}

	public UUID getIdcliente() {
		return idcliente;
	}

	public void setIdcliente(UUID idcliente) {
		this.idcliente = idcliente;
	}
	
	//*************** metodos para HELLO_RESPONSE
	

	//****************** metodos generales
	
	public byte getMessagetype() {
		return messagetype;
	}

	public void setMessagetype(byte messagetype) {
		this.messagetype = messagetype;
	}

	public int getIdfromserver() {
		return idfromserver;
	}

	public void setIdfromserver(int idfromserver) {
		this.idfromserver = idfromserver;
	}

	public int getNumCar() {
		return numCar;
	}

	public void setNumCar(int numCar) {
		this.numCar = numCar;
	}
	
	public String getMesageTypeAsString(){
		switch(this.messagetype){
		case IRazerProtocol.CARUPDATE_REQUEST:
			return "CARUPDATE_REQUEST";
		case IRazerProtocol.CARUPDATE_RESPONSE:
			return "CARUPDATE_RESPONSE";
		case IRazerProtocol.CREATEGAME_REQUEST:
			return "CREATEGAME_REQUEST";
		case IRazerProtocol.CREATEGAME_RESPONSE:
			return "CREATEGAME_RESPONSE";
		case IRazerProtocol.GAMEREADY_REQUEST:
			return "GAMEREADY_REQUEST";
		case IRazerProtocol.GAMEREADY_RESPONSE:
			return "GAMEREADY_RESPONSE";
		case IRazerProtocol.HELLO_REQUEST:
			return "HELLO_REQUEST";
		case IRazerProtocol.HELLO_RESPONSE:
			return "HELLO_RESPONSE";
		case IRazerProtocol.JOINGAME_REQUEST:
			return "JOINGAME_REQUEST";
		case IRazerProtocol.NOGAMETOJOIN_RESPONSE:
			return "NOGAMETOJOIN_RESPONSE";
		case IRazerProtocol.PLAYERADDED_RESPONSE:
			return "PLAYERADDED_RESPONSE";
		case IRazerProtocol.NOOP_RESPONSE:
			return "NOOP_RESPONSE";
		case IRazerProtocol.CLOSING_REQUEST:
			return "CLOSING_REQUEST";
		default:
			return null;
		}
	}

	public void setCarUpdate(ServerCar carupdate) {
		this.defaultcarupdate = carupdate;
		
	}

	public ServerCar getDefaultcarupdate() {
		return defaultcarupdate;
	}

	public void setDefaultcarupdate(ServerCar defaultcarupdate) {
		this.defaultcarupdate = defaultcarupdate;
	}

	public ServerCar getCar1update() {
		return car1update;
	}

	public void setCar1update(ServerCar car1update) {
		this.car1update = car1update;
	}

	public ServerCar getCar2update() {
		return car2update;
	}

	public void setCar2update(ServerCar car2update) {
		this.car2update = car2update;
	}

	public ServerCar getCar3update() {
		return car3update;
	}

	public void setCar3update(ServerCar car3update) {
		this.car3update = car3update;
	}

	public ServerCar getCar4update() {
		return car4update;
	}

	public void setCar4update(ServerCar car4update) {
		this.car4update = car4update;
	}
	
	
	@Override
	public boolean equals(Object obj) {
	       if (! (obj instanceof RazerProtocolMessage) ) return false;

	       final RazerProtocolMessage other = (RazerProtocolMessage) obj;
	       // y ahora miro el contenido
	       if (messagetype != other.getMessagetype()){
	           return false;
	       }
	       if(messagecontent!=other.getMessageContent()){
	    	   return false;
	       }
	       return true;

	}

	public void setResults(int[] is) {
		this.results = is;
		
	}
	
	public int[] getResults(){
		return this.results;
	}

}
